﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BasePlatformCom
{
	public class ComSubControl : BaseDevice
	{
		public int atMainPort = ComMainPort.Unknown;

		public int localDepth = -1;

		public int[] p_total = null;
		public int[] p_err = null;

		public bool hasWatchCard = false;
		public byte[] watchCardInfoBytes = null;

		public uint crc_err_count = 0;
		public uint package_count = 0;

		public byte[] replyData = new byte[256];

		// 构造函数
		public ComSubControl()
		{
			p_total = new int[9];
			p_err = new int[9];
			watchCardInfoBytes = new byte[0x1f];
		}

		// 重置 px_total、px_err
		public void resetPxInfo()
		{
			for (int k = 0; k < 9; k++)
			{
				p_total[k] = 0;
				p_err[k] = 0;
			}
		}

		// 检测分控版本, 获取 px_total、px_err, 获取箱体监控卡信息, 获取 crc_err_count、package_count, 参数 hubPort: 0 ~ 7
		public string detectSubControlVersion(SerialComPort currentComPort, int mainPort, int hubPort, int subIndex)
		{
			string version = "";

			bool effect = readSubMem(currentComPort, mainPort, hubPort, subIndex, 0, memData);

			if (effect == false)
			{
				return "";
			}

			Array.Copy(memData, 0, replyData, 0, 256);

			// 获取 crc_err_count, package_count
			crc_err_count = (uint)(memData[0x00] | memData[0x01] << 8);
			package_count = (uint)(memData[0x02] | memData[0x03] << 8 | memData[0x04] << 16 | memData[0x05] << 24);

			for (int i = 0x40; i <= 0x46; i++)
			{
				switch (i)
				{
					case 0x40:
						{
							version = chr(memData[i]);
							break;
						}
					case 0x41:
						{
							version += chr(memData[i]);
							break;
						}
					case 0x42:
						{
							version += memData[i];
							break;
						}
					case 0x43:
						{
							if (memData[i] < 10)
							{
								version = version + "0" + memData[i];
							}
							else
							{
								version = version + memData[i];
							}
							break;
						}
					case 0x44:
						{
							version = version + "_" + chr(memData[i]);
							break;
						}
					case 0x45:
						{
							if (memData[i] < 10)
							{
								version = version + "0" + memData[i];
							}
							else
							{
								version = version + memData[i];
							}
							break;
						}
					case 0x46:
						{
							if (memData[i] < 10)
							{
								version = version + "_X0" + memData[i];
							}
							else
							{
								version = version + "_X" + memData[i];
							}
							break;
						}
				}
			}

			// 获取 px_total、px_err（总点数、错误点数）
			resetPxInfo();
			int index = 0x80;
			for (int k = 1; k <= 8; k++)
			{
				p_total[k] = memData[index++] & 0xFF;
				p_total[k] |= ((memData[index++] << 8) & 0xFF00);
				p_err[k] = memData[index++] & 0xFF;
				p_err[k] |= ((memData[index++] << 8) & 0xFF00);
			}

			// 获取箱体监控卡信息
			if (memData[0x50] == 0xff)
			{
				hasWatchCard = true;
				Array.Copy(memData, 0x50, watchCardInfoBytes, 0, 0x1F);
			}
			else
			{
				hasWatchCard = false;
			}

			return version;
		}

		// 检测分控灯具信息, 参数 portIndex: 1 ~ 8, 每个端口最多连接 128 个灯, 返回 byte[] - To Update hubPort
		public byte[] detectLightDetailBytes(SerialComPort currentComPort, int mainPort, int hubPort, int subIndex, int portIndex)
		{
			if (hubPort != 0)
			{
				return null;
			}

			byte[] memData = new byte[256];

			int packetId = random.Next(256);
			int receiveError = 0;

			memData[0] = 0x5a;				// 命令标识
			memData[1] = 0xa5;				// 命令标识取反
			memData[2] = 0x25;				// 命令
			memData[3] = mod256(packetId);	// 包序号
			memData[4] = 0xff;				// 芯片号低
			memData[5] = 0xff;				// 芯片号高
			memData[6] = 0;					// 包长度低
			memData[7] = 0;					// 包长度高
			memData[8] = 0;					// CRC低
			memData[9] = 0;					// CRC
			memData[10] = 0;				// CRC
			memData[11] = 0;				// CRC高

			int cmdLength = 12;
			memData[6] = mod256(cmdLength - 1);

			int memAddr = 0x20A00000 + portIndex * 0x0100;
			writeSubMem(currentComPort, mainPort, subIndex, memAddr, memData);
			readSubMem(currentComPort, mainPort, hubPort, subIndex, 0x20A10000, memData);

			#region 构造数据 - 调试用
			/*
			try
			{
			    FileStream fs_data = new FileStream("dat.log", FileMode.Open, FileAccess.Read);
			    BinaryReader br = new BinaryReader(fs_data);
			    memData = br.ReadBytes(256);
			}
			catch (Exception ex)
			{
			    typeLog(ex.Message + ex.StackTrace);
			}
			return mem_data;
			*/
			#endregion

			// 判断通信有效性
			if (memData[3] != packetId)
			{
				receiveError = 1;
			}
			else
			{
				receiveError = 0;
			}

			if (receiveError == 1)
			{
				return null;
			}
			else
			{
				byte[] res = new byte[256];
				Array.Copy(memData, res, 256);
				return res;
			}
		}

		// 检测单个灯具信息
		public byte[] getLampStateBytes(SerialComPort currentComPort, int mainPort, int hubPort, int subIndex, int portIndex, int miniIndex)
		{
			//Console.WriteLine(string.Format("[ComSubControl] getLampStatePara, comPort = {0}, mainPort = {1}, subIndex = {2}, subPortIndex = {3}, miniIndex = {4}",
			//    currentComPort.PortName, mainPort, subIndex, portIndex, miniIndex));

			if (hubPort != 0)
			{
				return null;
			}

			byte[] memData = new byte[256];

			//int packetId = random.Next(256);
			int packetId = miniIndex % 256;
			int receiveError = 0;

			memData[0] = 0x5a;									// 命令标识
			memData[1] = 0xa5;									// 命令标识取反
			memData[2] = 0x61;									// 命令
			memData[3] = mod256(packetId);						// 包序号
			memData[4] = (byte)(0xff & miniIndex);				// 灯具地址低
			memData[5] = (byte)((0xff00 & miniIndex) >> 8);		// 灯具地址高
			memData[6] = 0;										// 包长度低
			memData[7] = 0;										// 包长度高
			memData[8] = 0;										// CRC低
			memData[9] = 0;										// CRC
			memData[10] = 0;									// CRC
			memData[11] = 0;									// CRC高

			int cmdLength = 10;
			memData[6] = mod256(cmdLength - 1);

			int memAddr = 0x20A00000 + portIndex * 0x0100;
			writeSubMem(currentComPort, mainPort, subIndex, memAddr, memData);
			readSubMem(currentComPort, mainPort, hubPort, subIndex, 0x20A10000, memData);

			// 判断通信有效性
			if (memData[3] != packetId)
			{
				receiveError = 1;
			}
			else
			{
				receiveError = 0;
			}

			if (receiveError == 1)
			{
				return null;
			}
			else
			{
				byte[] res = new byte[256];
				Array.Copy(memData, res, 256);
				return res;
			}
		}
	}
}
